<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0045)http://www.beyondlogic.org/serial/serial1.htm -->
<HTML>
<!-- Mirrored from bos.asmhackers.net/docs/serial/docs/serial1.htm by HTTrack Website Copier/3.x [XR&CO'2013], Tue, 07 Oct 2014 11:24:16 GMT -->
<HEAD><TITLE>Interfacing The Serial / RS-232 Port</TITLE>
<META http-equiv=Content-Type content="text/html; charset=windows-1251">
<META 
content="Describes interfacing the Serial (RS-232) Port in relation to both Hardware and Software. Gives Practical Examples using CDP6402 UART and Software Examples in C." 
name=description>
<META 
content="RS232, RS-232, Serial, CPD6402, AY-5-1015, 8250, 16450, 16550, 16650, 16750, UART, MAX-232, COMMS, COM Port, Serial Port, Terminal, Programming in C, Serial Programming, RS-232 Programming" 
name=keywords>
<META content="MSHTML 5.50.4611.1300" name=GENERATOR></HEAD>
<BODY background=serial1_files/background.gif>
<STYLE type=text/css>#TITLEBLOCK {
	COLOR: #ffffff; TEXT-DECORATION: none
}
TD {
	FONT-FAMILY: Arial
}
P {
	FONT-FAMILY: Arial
}
FONT {
	FONT-FAMILY: Arial
}
A {
	FONT-FAMILY: Arial
}
</STYLE>

<CENTER><BR><BR><A href="http://www.beyondlogic.org/"><IMG 
alt="Interfacing the PC / Beyond Logic" src="serial1_files/interface.gif" 
border=0></A> <BR>
<TABLE width="70%">
  <TBODY>
  <TR>
    <TD>
      <DIV align=right><FONT face=ARIAL size=+1>Quality Information in one Place 
      . . .</FONT></DIV></TD></TR></TBODY></TABLE><BR>
<TABLE width="90%" border=0>
  <TBODY>
  <TR>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#PARALLEL">Parallel 
      Ports</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#SERIAL">Serial 
      Ports</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#INTERRUPTS">Interrupts</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#ATKEYBOARDS">AT Keyboard 
      Ports</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#USB">USB</A></CENTER></B></FONT></TD></TR></TBODY></TABLE><BR><FONT 
size=+3>Interfacing the Serial / RS-232 Port</FONT> <BR><BR></CENTER>
<P>
<HR>
<I><FONT size=+2>
<CENTER>Table of Contents</CENTER></FONT></I>
<HR>

<P></P>
<P>
<CENTER><FONT size=+1><B>Part 1 : Hardware (PC's)</B></FONT><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#1">Hardware 
Properties</A><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#2">Serial Pinouts (D25 and D9 
connectors)<BR><A href="http://www.beyondlogic.org/serial/serial.htm#3">Pin 
Functions </A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#4">Null 
Modems </A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#5">Loopback 
Plugs</A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#6">DTE/DCE 
Speeds</A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#7">Flow 
Control </A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#8">The 
UART (8250's and Compatibles) </A><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#9">Type of UARTS (For PC's) 
</A><BR><FONT size=+1><B>Part 2 : Serial Ports' Registers 
(PC's)</B></FONT><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#12">Port Addresses and 
IRQ's</A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#13">Table of 
Registers</A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#14">DLAB 
? </A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#15">Interrupt 
Enable Register (IER)</A><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#16">Interrupt Identification 
Register (IIR)</A><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#17">First In / First Out 
Control Register (FCR)</A><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#18">Line Control Register 
(LCR)</A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#19">Modem 
Control Register (MCR)</A><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#20">Line Status Register 
(LSR)</A><BR><A href="http://www.beyondlogic.org/serial/serial.htm#21">Modem 
Status Register (MSR)</A><BR><A 
href="http://www.beyondlogic.org/serial/serial.htm#22">Scratch 
Register</A><BR><FONT size=+1><B>Part 3 : Programming (PC's)</B></FONT><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#30">Polling or Interrupt 
Driven?</A><BR><A href="http://www.beyondlogic.org/serial/termpoll.c">Source 
Code - Termpoll.c (Polling Version)</A><BR><A 
href="http://www.beyondlogic.org/serial/buff1024.c">Source Code - Buff1024.c 
(ISR Version) </A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#31">Interrupt 
Vectors</A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#32">Interrupt Service 
Routine</A><BR><A href="http://www.beyondlogic.org/serial/serial1.htm#33">UART 
Configuration</A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#34">Main Routine 
(Loop)</A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#35">Determining the type of 
UART via Software</A><BR><FONT size=+1><B>Part 4 : External Hardware - 
Interfacing Methods</B></FONT><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#40">RS-232 
Waveforms</A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#41">RS-232 Level 
Converters</A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#42">Making use of the Serial 
Format</A><BR><A href="http://www.beyondlogic.org/serial/serial1.htm#43">8250 
and compatible UART's</A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#44">CDP6402, AY-5-1015 / 
D36402R-9 etc UARTs</A><BR><A 
href="http://www.beyondlogic.org/serial/serial1.htm#46">Microcontrollers</A><BR>
<P></P></CENTER>
<P><A name=Part3></A>
<HR>
</A><I><FONT size=+2>Part 3 : Programming (PC's)</FONT></I>
<HR>

<P></P>
<UL><A name=30><FONT size=+1>Polling or Interrupt Driven?</FONT><BR>
  <HR>
  </A>
  <P>When writing a communications program you have two methods available to 
  you. You can poll the UART, to see if any new data is available or you can set 
  up an interrupt handler to remove the data from the UART when it generates a 
  interrupt. Polling the UART is a lot slower method, which is very CPU 
  intensive thus can only have a maximum speed of around 34.8 KBPS before you 
  start losing data. Some newer Pentium Pro's may be able to achieve better 
  rates that this. The other option is using a Interrupt handler, and that's 
  what we have used here. It will very easily support 115.2K BPS, even on low 
  end computers. </P>
  <P>
  <CENTER><A href="http://www.beyondlogic.org/serial/termpoll.c">Termpoll.c - 
  Simple Terminal Program using the Polling Method.</A> </CENTER>
  <P></P>
  <P>Polling the UART should not be dismissed totally. It's a good method for 
  diagnostics. If you have no idea of what address your card is at or what IRQ 
  you are using you can poll the UART at several different addresses to firstly 
  find which port your card is at and which one your modem is attached to. Once 
  you know this information, then you can set up the Interrupt routines for the 
  common IRQs and by enabling one IRQ at a time using the Programmable Interrupt 
  Controller you can find out your IRQ, You don't even need a screw driver! </P>
  <P>
  <CENTER><A href="http://www.beyondlogic.org/serial/buff1024.c">Buff1024.c - 
  Simple Terminal Program using Interrupt Requests.</A> </CENTER>
  <P></P>
  <P>
  <CENTER>
  <TABLE width="90%">
    <TBODY>
    <TR>
      <TD vAlign=top>Note:</TD>
      <TD><I>The source code above is not a really good example on how to 
        program but is rather cut down to size giving quick results, and making 
        it easier to understand. Upon executing your communications program, it 
        would be wise to store the status of the UART registers, so that they 
        all can be restored before you quit the program. This is to cause the 
        least upset to other programs which may also be trying to use the 
        communications ports. </I></TD></TR></TBODY></TABLE></CENTER>
  <P>The first step to using interrupts is to work out which interrupt services 
  your serial card. Table 13 shows the base addresses and IRQ's of some standard 
  ports. IRQ's 3 and 4 are the two most commonly used. IRQ 5 and 7 are sometimes 
  used. </P><A name=31><FONT size=+1>Interrupt Vectors</FONT><BR>
  <HR>
  </A>
  <P>Once we know the IRQ the next step is to find it's interrupt vector or 
  software interrupt as some people may call it. Basically any 8086 processor 
  has a set of 256 interrupt vectors numbered 0 to 255. Each of these vectors 
  contains a 4 byte code which is an address of the Interrupt Service Routine 
  (ISR). Fortunately C being a high level language, takes care of the addresses 
  for us. All we have to know is the actual interrupt vector. </P>
  <CENTER>
  <TABLE width="80%" border=1>
    <TBODY>
    <TR>
      <TD>
        <CENTER><B>INT (Hex)</B></CENTER></TD>
      <TD><B>
        <CENTER>IRQ</CENTER></B></TD>
      <TD><B>Common Uses</B></TD></TR>
    <TR>
      <TD>
        <CENTER>08</CENTER></TD>
      <TD>
        <CENTER>0</CENTER></TD>
      <TD>System Timer</TD></TR>
    <TR>
      <TD>
        <CENTER>09</CENTER></TD>
      <TD>
        <CENTER>1</CENTER></TD>
      <TD>Keyboard</TD></TR>
    <TR>
      <TD>
        <CENTER>0A</CENTER></TD>
      <TD>
        <CENTER>2</CENTER></TD>
      <TD>Redirected</TD></TR>
    <TR>
      <TD>
        <CENTER>0B</CENTER></TD>
      <TD>
        <CENTER>3</CENTER></TD>
      <TD>Serial Comms. COM2/COM4</TD></TR>
    <TR>
      <TD>
        <CENTER>0C</CENTER></TD>
      <TD>
        <CENTER>4</CENTER></TD>
      <TD>Serial Comms. COM1/COM3 </TD></TR>
    <TR>
      <TD>
        <CENTER>0D</CENTER></TD>
      <TD>
        <CENTER>5</CENTER></TD>
      <TD>Reserved/Sound Card </TD></TR>
    <TR>
      <TD>
        <CENTER>0E</CENTER></TD>
      <TD>
        <CENTER>6</CENTER></TD>
      <TD>Floppy Disk Controller </TD></TR>
    <TR>
      <TD>
        <CENTER>0F</CENTER></TD>
      <TD>
        <CENTER>7</CENTER></TD>
      <TD>Parallel Comms. </TD></TR>
    <TR>
      <TD>
        <CENTER>70</CENTER></TD>
      <TD>
        <CENTER>8</CENTER></TD>
      <TD>Real Time Clock</TD></TR>
    <TR>
      <TD>
        <CENTER>71</CENTER></TD>
      <TD>
        <CENTER>9</CENTER></TD>
      <TD>Reserved</TD></TR>
    <TR>
      <TD>
        <CENTER>72</CENTER></TD>
      <TD>
        <CENTER>10</CENTER></TD>
      <TD>Reserved</TD></TR>
    <TR>
      <TD>
        <CENTER>73</CENTER></TD>
      <TD>
        <CENTER>11</CENTER></TD>
      <TD>Reserved</TD></TR>
    <TR>
      <TD>
        <CENTER>74</CENTER></TD>
      <TD>
        <CENTER>12</CENTER></TD>
      <TD>PS/2 Mouse</TD></TR>
    <TR>
      <TD>
        <CENTER>75</CENTER></TD>
      <TD>
        <CENTER>13</CENTER></TD>
      <TD>Maths Co-Processor</TD></TR>
    <TR>
      <TD>
        <CENTER>76</CENTER></TD>
      <TD>
        <CENTER>14</CENTER></TD>
      <TD>Hard Disk Drive</TD></TR>
    <TR>
      <TD>
        <CENTER>77</CENTER></TD>
      <TD>
        <CENTER>15</CENTER></TD>
      <TD>Reserved </TD></TR></TBODY></TABLE><FONT size=-1>Table 14 : Interrupt 
  Vectors (Hardware Only) </FONT></CENTER>
  <P>The above table shows only the interrupts which are associated with IRQ's. 
  The other 240 are of no interest to us when programming RS-232 type 
  communications. </P>
  <P>For example if we were using COM3 which has a IRQ of 4, then the interrupt 
  vector would be 0C in hex. Using C we would set up the vector using the 
  instruction <FONT color=#400080><TT>setvect(0x0C, PORT1INT);</TT></FONT> where 
  PORT1INT would lead us to a set of instructions which would service the 
  interrupt. </P>
  <P>However before we proceed with that I should say that it is wise to record 
  the old vectors address and then restore that address once the program is 
  finished. This is done using <FONT color=#400080><TT>oldport1isr = 
  getvect(INTVECT);</TT></FONT> where oldport1isr is defined using <FONT 
  color=#400080><TT>void interrupt (*oldport1isr)(); </TT></FONT></P>
  <P>Not only should you store the old vector addresses, but also the 
  configuration the UART was in. Why you Ask? Well it's simple, I wrote a 
  communications program which was fully featured in the chat side of things. It 
  had line buffering, so no body could see my spelling mistakes or how slowly I 
  typed. It included anti-bombing routines and the list goes on. However I 
  couldn't be bothered to program any file transfer protocols such as Zmodem etc 
  into my communications program. Therefore I either had to run my 
  communications program in the background of Telemate using my communications 
  program for chat and everything else it was designed for and using Telemate to 
  download files. Another method was to run, say Smodem as a external protocol 
  to my communications program. </P>
  <P>Doing this however would mean that my communications program would override 
  the original speed, parity etc and then when I returned to the original 
  communications program, everything stopped. Therefore by saving the old 
  configuration, you can revert back to it before you hand the UART back over to 
  the other program. Makes sense? However if you don't have any of these 
  programs you can save yourself a few lines of code. This is what we have done 
  here. </P><A name=32><FONT size=+1>Interrupt Service Routine (ISR)</FONT><BR>
  <HR>
  </A>
  <P>Now, could we be off track just a little? Yes that's right, PORT1INT is the 
  label to our interrupt handler called a Interrupt Service Routine (ISR). You 
  can put just about anything in here you want. However calling some DOS 
  routines can be a problem. </P><FONT color=#400080><PRE>void interrupt PORT1INT()
{
 int c;
 do { c = inportb(PORT1 + 5);
      if (c &amp; 1) {
                  buffer[bufferin] = inportb(PORT1);
                  bufferin++;
                  if (bufferin == 1024) bufferin = 0;
                 } 
    } while (c &amp; 1);
outportb(0x20,0x20);
}
</PRE></FONT>
  <P>From the example above we check to see if there is a character to receive 
  and if their is we remove it from the UART and place it in a buffer contained 
  in memory. We keep on checking the UART, in case FIFO's are enabled, so we can 
  get all data available at the time of interrupt. </P>
  <P>The last line contains the instruction <FONT 
  color=#400080><TT>outportb(0x20,0x20);</TT></FONT> which tells the 
  Programmable Interrupt Controller that the interrupt has finished. The 
  Programmable Interrupt Controller (PIC) is what we must go into now. All of 
  the routines above, we have assumed that everything is set up ready to go. 
  That is all the UART's registers are set correctly and that the Programmable 
  Interrupt Controller is set. </P>
  <P>The Programmable Interrupt Controller handles hardware interrupts. Most 
  PC's will have two of them located at different addresses. One handles IRQ's 0 
  to 7 and the other IRQ's 8 to 15. Mainly Serial communications interrupts 
  reside on IRQ's under 7, thus PIC1 is used, which is located at 0020 Hex. </P>
  <CENTER>
  <TABLE width="80%" border=1>
    <TBODY>
    <TR>
      <TD>
        <CENTER><B>Bit</B></CENTER></TD>
      <TD>
        <CENTER><B>Disable IRQ</B></CENTER></TD>
      <TD>
        <CENTER><B>Function</B></CENTER></TD></TR>
    <TR>
      <TD>
        <CENTER>7</CENTER></TD>
      <TD>
        <CENTER>IRQ7</CENTER></TD>
      <TD>Parallel Port</TD></TR>
    <TR>
      <TD>
        <CENTER>6</CENTER></TD>
      <TD>
        <CENTER>IRQ6</CENTER></TD>
      <TD>Floppy Disk Controller</TD></TR>
    <TR>
      <TD>
        <CENTER>5</CENTER></TD>
      <TD>
        <CENTER>IRQ5</CENTER></TD>
      <TD>Reserved/Sound Card</TD></TR>
    <TR>
      <TD>
        <CENTER>4</CENTER></TD>
      <TD>
        <CENTER>IRQ4</CENTER></TD>
      <TD>Serial Port</TD></TR>
    <TR>
      <TD>
        <CENTER>3</CENTER></TD>
      <TD>
        <CENTER>IRQ3</CENTER></TD>
      <TD>Serial Port</TD></TR>
    <TR>
      <TD>
        <CENTER>2</CENTER></TD>
      <TD>
        <CENTER>IRQ2</CENTER></TD>
      <TD>PIC2</TD></TR>
    <TR>
      <TD>
        <CENTER>1</CENTER></TD>
      <TD>
        <CENTER>IRQ1</CENTER></TD>
      <TD>Keyboard</TD></TR>
    <TR>
      <TD>
        <CENTER>0</CENTER></TD>
      <TD>
        <CENTER>IRQ0</CENTER></TD>
      <TD>System Timer</TD></TR></TBODY></TABLE><FONT size=-1>Table 15 : PIC1 
  Control Word (0x21)</FONT> </CENTER>
  <P>Multi-Comm ports are getting quite common, thus table 16 includes data for 
  PIC2 which is located at 0xA0. PIC2 is responsible for IRQ's 8 to 15. It 
  operates in exactly the same way than PIC1 except that EOI's (End of 
  Interrupt) goes to port 0xA0 while the disabling (Masking) of IRQ's are done 
  using port 0xA1. </P>
  <CENTER>
  <TABLE width="80%" border=1>
    <TBODY>
    <TR>
      <TD>
        <CENTER><B>Bit</B></CENTER></TD>
      <TD>
        <CENTER><B>Disable IRQ</B></CENTER></TD>
      <TD>
        <CENTER><B>Function</B></CENTER></TD></TR>
    <TR>
      <TD>
        <CENTER>7</CENTER></TD>
      <TD>
        <CENTER>IRQ15</CENTER></TD>
      <TD>Reserved</TD></TR>
    <TR>
      <TD>
        <CENTER>6</CENTER></TD>
      <TD>
        <CENTER>IRQ14</CENTER></TD>
      <TD>Hard Disk Drive</TD></TR>
    <TR>
      <TD>
        <CENTER>5</CENTER></TD>
      <TD>
        <CENTER>IRQ13</CENTER></TD>
      <TD>Maths Co-Processor</TD></TR>
    <TR>
      <TD>
        <CENTER>4</CENTER></TD>
      <TD>
        <CENTER>IRQ12</CENTER></TD>
      <TD>PS/2 Mouse</TD></TR>
    <TR>
      <TD>
        <CENTER>3</CENTER></TD>
      <TD>
        <CENTER>IRQ11</CENTER></TD>
      <TD>Reserved</TD></TR>
    <TR>
      <TD>
        <CENTER>2</CENTER></TD>
      <TD>
        <CENTER>IRQ10</CENTER></TD>
      <TD>Reserved</TD></TR>
    <TR>
      <TD>
        <CENTER>1</CENTER></TD>
      <TD>
        <CENTER>IRQ9</CENTER></TD>
      <TD>IRQ2</TD></TR>
    <TR>
      <TD>
        <CENTER>0</CENTER></TD>
      <TD>
        <CENTER>IRQ8</CENTER></TD>
      <TD>Real Time Clock</TD></TR></TBODY></TABLE><FONT size=-1>Table 16 : PIC2 
  Control Word (0xA1) </FONT></CENTER>
  <P>Most of the PIC's initiation is done by BIOS. All we have to worry about is 
  two instructions. The first one is <FONT 
  color=#400080><TT>outportb(0x21,(inportb(0x21) &amp; 0xEF);</TT></FONT> which 
  selects which interrupts we want to Disable (Mask). So if we want to enable 
  IRQ4 we would have to take 0x10 (16) from 0xFF (255) to come up with 0xEF 
  (239). That means we want to disable IRQ's 7,6,5,3,2,1 and 0, thus enabling 
  IRQ 4. </P>
  <P>But what happens if one of these IRQs are already enabled and then we come 
  along and disable it? Therefore we input the value of the register and using 
  the &amp; function output the byte back to the register with our changes using 
  the instruction <FONT color=#400080><TT>outportb(0x21,(inportb(0x21) &amp; 
  0xEF);</TT></FONT>. For example if IRQ5 is already enabled before we come 
  along, it will enable both IRQ4 and IRQ5 so we don't make any changes which 
  may affect other programs or TSR's. </P>
  <P>The other instruction is <FONT 
  color=#400080><TT>outportb(0x20,0x20);</TT></FONT> which signals an end of 
  interrupt to the PIC. You use this command at the end of your interrupt 
  service routine, so that interrupts of a lower priority will be accepted. 
  </P><A name=33><FONT size=+1>UART Configuration</FONT><BR>
  <HR>
  </A>
  <P>Now we get to the UART settings (Finally) </P>
  <P>It's a good idea to turn off the interrupt generation on the UART as the 
  first instruction. Therefore your initialization can't get interrupted by the 
  UART. I've then chosen to set up our interrupt vectors at this point. The next 
  step is to set the speed at which you wish to communicate at. If you remember 
  the process, we have to set bit 7 (The DLAB) of the LCR so we can access the 
  Divisor Latch High and Low Bytes. We have decided to set the speed to 38,400 
  Bits per second which should be find for 16450's and 16550's. This requires a 
  divisor of 3, thus our divisor latch high byte will be 0x00 and a divisor 
  latch low byte, 0x03. </P>
  <P>In today's standards the divisor low latch byte is rarely used but it still 
  pays us to write 0x00 to the register just in case the program before us just 
  happened to set the UART at a very very low speed. BIOS will normally set 
  UARTs at 2400 BPS when the computer is first booted up which still doesn't 
  require the Divisor Latch Low byte. </P>
  <P>The next step would be to turn off the Divisor latch access bit so we can 
  get to the Interrupt Enable Register and the receiver/transmitter buffers. 
  What we could do is just write a 0x00 to the register clearing it all, but 
  considering we have to set up our word length, parity as so forth in the line 
  control register we can do this at the same time. We have decided to set up 8 
  bits, no parity and 1 stop bit which is normally used today. Therefore we 
  write 0x03 to the line control register which will also turn off the DLAB for 
  us saving one more I/O instruction. </P>
  <P>The next line of code turns on the FIFO buffers. We have made the trigger 
  level at 14 bytes, thus bits 6 and 7 are on. We have also enabled the FIFO's 
  (bit 0). It's also good practice to clear out the FIFO buffers on 
  initialization. This will remove any rubbish which the last program may of 
  left in the FIFO buffers. Due to the fact that these two bits are self 
  resetting, we don't have to go any further and turn off these bits. If my 
  arithmetic is correct all these bits add up to 0xC7 or 199 for those people 
  which still work in decimal. </P>
  <P>Then DTR, RTS and OUT 2 is taken active by the instruction <FONT 
  color=#400080><TT>outportb(PORT1 + 4,0x0B);</TT></FONT>. Some cards (Both of 
  Mine) require OUT2 active for interrupt requests thus I'm normally always take 
  it high. All that is left now is to set up our interrupts which has be 
  deliberately left to last as to not interrupt our initialization. Our 
  interrupt handler is only interested in new data being available so we have 
  only set the UART to interrupt when data is received. </P><A name=34><FONT 
  size=+1>Main Routine (Loop)</FONT><BR>
  <HR>
  </A>
  <P>Now we are left with, </P><FONT color=#400080><PRE>do {
    if (bufferin != bufferout){
                               ch = buffer[bufferout];
                               bufferout++;
                               if (bufferout == 1024) bufferout = 0;
                               printf("%c",ch);
                              }
    if (kbhit()){
                 c = getch();
                 outportb(PORT1, c);
                }
   } while (c !=27);
</PRE></FONT>
  <P>which keeps repeating until c = 27. This occurs when the ESC key is hit. 
  </P>
  <P>The next <I>if</I> statement checks to see if a key has been hit. (<FONT 
  color=#400080><TT>kbhit()</TT></FONT>) If so, it gets the character using the 
  <FONT color=#400080><TT>getch()</TT></FONT> statement and outputs it to the 
  receiver buffer. The UART then transmits the character to the modem. What we 
  have assumed here, is that the person using the Communications Program can't 
  type as fast as the UART can send. However if the program wishes to send 
  something, then a check should be made to see if BIT 5 of the Line Status 
  Register is set before attempting to send a byte to the transmitter register. 
  </P>
  <P>
  <CENTER><I>For more information on Interrupts, try <A 
  href="http://www.beyondlogic.org/interrupts/interupt.htm">"Interfacing the PC 
  : Using Interrupts"</A></I></CENTER>
  <P></P>
  <P><A name=35></A><FONT size=+1>Determining the type of UART via 
  software</FONT><BR>
  <HR>

  <P></P>
  <P>The type of UART you have installed in your system can be determined 
  without even needing a screwdriver in most cases. As you can see from <A 
  href="http://www.beyondlogic.org/serial/serial.htm#9">Types of UART's</A> each 
  UART has minor differences, all we have to do it test these. </P>
  <P>The first procedure we do is to set bit 0 to '1' in the FIFO control 
  register. This tries to enable the FIFO buffers. Then we read bits 6 and 7 
  from the interrupt identification register. If both bits are '1' then the FIFO 
  buffers are enabled. This would mean the UART is a 16550a. If the FIFO's were 
  enabled but not usable then it would be a 16550. If there is no FIFO buffer 
  enabled it is most likely to be a 16450 UART, but could be a 8250, 8250A or 
  8250B on very old systems. </P>
  <P>AT's have a fast bus speed which the 8250 series of UART can't handle to 
  well thus it is very unlikely to be found in any AT. However if you wish to 
  test for them as well you can follow the same test as above to distinguish 
  16550's or 16550A's from the rest. If no FIFOs are enabled then a possible 
  UART is the 16450, 8250, 8250A or 8250B. Once it is established the it could 
  be one of these four chips, try writing a byte to the scratch register and 
  then read it back and compare the results. If the results match then you must 
  have a scratch register, if they don't you either don't have a scratch 
  register, or it doesn't work to well. </P>
  <P>From the descriptions of the UART above if you read back your byte from the 
  scratch register then the UART must be a 16450 or 8250A. (Both have scratch 
  registers) If you don't read back your byte then it's either a 8250 or 8250B. 
  </P>
  <P>The 16750 has 64 byte FIFO's, thus the easiest way to test for it's 
  presence is to enable the 64 byte buffer using the FIFO Control Register and 
  then read back the status of the Interrupt Identification Register. However I 
  have never tested this. </P></UL><A name=Part4></A>
<HR>
<I><FONT size=+2>Part 4 : Interfacing Devices to RS-232 Ports</FONT></I> 
<HR>

<P></P>
<UL><A name=40><FONT size=+1>RS-232 Waveforms</FONT><BR>
  <HR>
  </A>
  <P>So far we have introduced RS-232 Communications in relation to the PC. 
  RS-232 communication is asynchronous. That is a clock signal is not sent with 
  the data. Each word is synchronized using it's start bit, and an internal 
  clock on each side, keeps tabs on the timing. </P>
  <CENTER>
  <P><IMG alt="Serial Waveforms - Logic Levels" src="serial1_files/serwave1.gif" 
  border=0> <BR><FONT size=-1>Figure 4 : TTL/CMOS Serial Logic Waveform</FONT> 
  </CENTER>
  <P>The diagram above, shows the expected waveform from the UART when using the 
  common 8N1 format. 8N1 signifies 8 Data bits, No Parity and 1 Stop Bit. The 
  RS-232 line, when idle is in the Mark State (Logic 1). A transmission starts 
  with a start bit which is (Logic 0). Then each bit is sent down the line, one 
  at a time. The LSB (Least Significant Bit) is sent first. A Stop Bit (Logic 1) 
  is then appended to the signal to make up the transmission. </P>
  <P>The diagram, shows the next bit after the Stop Bit to be Logic 0. This must 
  mean another word is following, and this is it's Start Bit. If there is no 
  more data coming then the receive line will stay in it's idle state(logic 1). 
  We have encountered something called a "Break" Signal. This is when the data 
  line is held in a Logic 0 state for a time long enough to send an entire word. 
  Therefore if you don't put the line back into an idle state, then the 
  receiving end will interpret this as a break signal. </P>
  <P>The data sent using this method, is said to be <I>framed</I>. That is the 
  data is <I>framed</I> between a Start and Stop Bit. Should the Stop Bit be 
  received as a Logic 0, then a framing error will occur. This is common, when 
  both sides are communicating at different speeds. </P>
  <P>The above diagram is only relevant for the signal immediately at the UART. 
  RS-232 logic levels uses +3 to +25 volts to signify a "Space" (Logic 0) and -3 
  to -25 volts for a "Mark" (logic 1). Any voltage in between these regions (ie 
  between +3 and -3 Volts) is undefined. Therefore this signal is put through a 
  "RS-232 Level Converter". This is the signal present on the RS-232 Port of 
  your computer, shown below. </P>
  <CENTER>
  <P><IMG alt="RS-232 Waveforms" src="serial1_files/serwave2.gif" border=0> 
  <BR><FONT size=-1>Figure 5 : RS-232 Logic Waveform</FONT> </CENTER>
  <P>The above waveform applies to the Transmit and Receive lines on the RS-232 
  port. These lines carry serial data, hence the name Serial Port. There are 
  other lines on the RS-232 port which, in essence are <I>Parallel</I> lines. 
  These lines (RTS, CTS, DCD, DSR, DTR, RTS and RI) are also at RS-232 Logic 
  Levels. </P>
  <P><A name=41><FONT size=+1>RS-232 Level Converters</FONT><BR>
  <HR>
  </A>
  <P></P>
  <P>Almost all digital devices which we use require either TTL or CMOS logic 
  levels. Therefore the first step to connecting a device to the RS-232 port is 
  to transform the RS-232 levels back into 0 and 5 Volts. As we have already 
  covered, this is done by RS-232 Level Converters. </P>
  <P>Two common RS-232 Level Converters are the 1488 RS-232 Driver and the 1489 
  RS-232 Receiver. Each package contains 4 inverters of the one type, either 
  Drivers or Receivers. The driver requires two supply rails, +7.5 to +15v and 
  -7.5 to -15v. As you could imagine this may pose a problem in many instances 
  where only a single supply of +5V is present. However the advantages of these 
  I.C's are they are cheap. </P>
  <CENTER>
  <TABLE>
    <TBODY>
    <TR>
      <TD>
        <CENTER><IMG alt="Pinout for MAX-232 RS-232 Level Converter" 
        src="serial1_files/max232.gif" border=0> </CENTER>Above: (Figure 6) 
        Pinouts for the MAX-232,<BR>RS-232 Driver/Receiver.<BR><BR>
        <HR>
        Right: (Figure 7) Typical MAX-232 Circuit.<BR><BR></TD>
      <TD><IMG alt="Typical MAX-232 Circuit" src="serial1_files/max232a.gif" 
        border=0> </TD></TR></TBODY></TABLE></CENTER>
  <P>Another device is the MAX-232. It includes a Charge Pump, which generates 
  +10V and -10V from a single 5v supply. This I.C. also includes two receivers 
  and two transmitters in the same package. This is handy in many cases when you 
  only want to use the Transmit and Receive data Lines. You don't need to use 
  two chips, one for the receive line and one for the transmit. However all this 
  convenience comes at a price, but compared with the price of designing a new 
  power supply it is very cheap. </P>
  <P>There are also many variations of these devices. The large value of 
  capacitors are not only bulky, but also expensive. Therefore other devices are 
  available which use smaller capacitors and even some with inbuilt capacitors. 
  <I>(Note : Some MAX-232's can use 1 micro farad Capacitors).</I> However the 
  MAX-232 is the most common, and thus we will use this RS-232 Level Converter 
  in our examples. </P>
  <P><A name=42><FONT size=+1>Making use of the Serial Format</FONT>
  <HR>
  </A>
  <P></P>
  <P>In order to do anything useful with our Serially transmitted data, we must 
  convert it back to Parallel. <I>(You could connect an LED to the serial port 
  and watch it flash if you really want too, but it's not extremely useful)</I>. 
  This in the past has been done with the use of UART's. However with the 
  popularity of cheap Microcontroller's, these can be more suited to many 
  applications. We will look into the advantages and disadvantages of each 
  method. </P><A name=43><FONT size=+1>8250 and Compatible UARTs</FONT><BR>
  <HR>
  </A>
  <P>We have already looked at one type of UART, the 8250 and compatibles found 
  in your PC. These devices have configuration registers accessible via the data 
  and address buses which have to be initialized before use. This is not a 
  problem if your device which you are building uses a Microprocessor. However 
  if you are making a stand alone device, how are you going to initialize it? 
  </P>
  <P>Most Microprocessors / Microcontrollers these days can be brought with 
  build-in Serial Communication Interfaces (SCI). Therefore there is little need 
  to connect a 40 pin 16550 to, for example a 68HC11 when you can buy one built 
  in. If you are still in love with the Z-80 or 8086 then an 16550 may be 
  option! <I>(or if you are like myself, the higher chip count the better. After 
  all it looks more complicated and impressive! - But a headache to debug!)</I> 
  </P>
  <CENTER>
  <P><IMG height=293 alt="Pin Diagrams of UARTs - 16550, 16450 &amp; 8250" 
  src="serial1_files/uart.gif" width=520 border=0> <BR><FONT size=-1>Figure 8 : 
  Pin Diagrams for 16550, 16450 &amp; 8250 UARTs</FONT></P></CENTER>
  <P>
  <CENTER>
  <TABLE width="80%" border=1>
    <TBODY>
    <TR>
      <TD width="10%">
        <CENTER><B>Pin No.</B></CENTER></TD>
      <TD width="15%">
        <CENTER><B>Name</B></CENTER></TD>
      <TD><B>Notes</B></TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 1:8</CENTER></TD>
      <TD>
        <CENTER>D0:D7</CENTER></TD>
      <TD>Data Bus</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 9</CENTER></TD>
      <TD>
        <CENTER>RCLK</CENTER></TD>
      <TD>Receiver Clock Input. The frequency of this input should equal the 
        receivers baud rate x 16</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 10</CENTER></TD>
      <TD>
        <CENTER>RD</CENTER></TD>
      <TD>Receive Data</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 11</CENTER></TD>
      <TD>
        <CENTER>TD</CENTER></TD>
      <TD>Transmit Data</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 12</CENTER></TD>
      <TD>
        <CENTER>CS0</CENTER></TD>
      <TD>Chip Select 0 - Active High</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 13</CENTER></TD>
      <TD>
        <CENTER>CS1</CENTER></TD>
      <TD>Chip Select 1 - Active High</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 14</CENTER></TD>
      <TD>
        <CENTER>nCS2</CENTER></TD>
      <TD>Chip Select 2 - Active Low</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 15</CENTER></TD>
      <TD>
        <CENTER>nBAUDOUT</CENTER></TD>
      <TD>Baud Output - Output from Programmable Baud Rate Generator. 
        Frequency = (Baud Rate x 16)</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 16</CENTER></TD>
      <TD>
        <CENTER>XIN</CENTER></TD>
      <TD>External Crystal Input - Used for Baud Rate Generator 
    Oscillator</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 17</CENTER></TD>
      <TD>
        <CENTER>XOUT</CENTER></TD>
      <TD>External Crystal Output</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 18</CENTER></TD>
      <TD>
        <CENTER>nWR</CENTER></TD>
      <TD>Write Line - Inverted</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 19</CENTER></TD>
      <TD>
        <CENTER>WR</CENTER></TD>
      <TD>Write Line - Not Inverted</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 20</CENTER></TD>
      <TD>
        <CENTER>VSS</CENTER></TD>
      <TD>Connected to Common Ground</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 21</CENTER></TD>
      <TD>
        <CENTER>RD</CENTER></TD>
      <TD>Read Line - Inverted</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 22</CENTER></TD>
      <TD>
        <CENTER>nRD</CENTER></TD>
      <TD>Read Line - Not Inverted</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 23</CENTER></TD>
      <TD>
        <CENTER>DDIS</CENTER></TD>
      <TD>Driver Disable. This pin goes low when CPU is reading from UART. Can 
        be connected to Bus Transceiver in case of high capacity data bus.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 24</CENTER></TD>
      <TD>
        <CENTER>nTXRDY</CENTER></TD>
      <TD>Transmit Ready</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 25</CENTER></TD>
      <TD>
        <CENTER>nADS</CENTER></TD>
      <TD>Address Strobe. Used if signals are not stable during read or write 
        cycle</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 26</CENTER></TD>
      <TD>
        <CENTER>A2</CENTER></TD>
      <TD>Address Bit 2</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 27</CENTER></TD>
      <TD>
        <CENTER>A1</CENTER></TD>
      <TD>Address Bit 1</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 28</CENTER></TD>
      <TD>
        <CENTER>A0</CENTER></TD>
      <TD>Address Bit 0</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 29</CENTER></TD>
      <TD>
        <CENTER>nRXRDY</CENTER></TD>
      <TD>Receive Ready</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 30</CENTER></TD>
      <TD>
        <CENTER>INTR</CENTER></TD>
      <TD>Interrupt Output</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 31</CENTER></TD>
      <TD>
        <CENTER>nOUT2</CENTER></TD>
      <TD>User Output 2</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 32</CENTER></TD>
      <TD>
        <CENTER>nRTS</CENTER></TD>
      <TD>Request to Send</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 33</CENTER></TD>
      <TD>
        <CENTER>nDTR</CENTER></TD>
      <TD>Data Terminal Ready</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 34</CENTER></TD>
      <TD>
        <CENTER>nOUT1</CENTER></TD>
      <TD>User Output 1</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 35</CENTER></TD>
      <TD>
        <CENTER>MR</CENTER></TD>
      <TD>Master Reset</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 36</CENTER></TD>
      <TD>
        <CENTER>nCTS</CENTER></TD>
      <TD>Clear To Send</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 37</CENTER></TD>
      <TD>
        <CENTER>nDSR</CENTER></TD>
      <TD>Data Set Ready</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 38</CENTER></TD>
      <TD>
        <CENTER>nDCD</CENTER></TD>
      <TD>Data Carrier Detect</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 39</CENTER></TD>
      <TD>
        <CENTER>nRI</CENTER></TD>
      <TD>Ring Indicator</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 40</CENTER></TD>
      <TD>
        <CENTER>VDD</CENTER></TD>
      <TD>+ 5 Volts</TD></TR></TBODY></TABLE><FONT size=-1>
  <CENTER>Table 17 : Pin Assignments for 16550A UART</CENTER></FONT></CENTER>
  <P></P>
  <P><I>For more information on the 16550 and compatible UART's see <A 
  href="http://www.beyondlogic.org/serial/serial.htm#8">The UART (8250's and 
  Compatibles)</A> in the first part of this tutorial.</I> </P><A name=44><FONT 
  size=+1>CDP6402, AY-5-1015 / D36402R-9 etc UARTs</FONT><BR>
  <HR>
  </A><BR>
  <TABLE>
    <TBODY>
    <TR>
      <TD>
        <CENTER><IMG alt="Pinout for CDP6402, AY-5-1015 / D36402R-9 UARTs" 
        src="serial1_files/6402.gif" border=0> <BR><FONT size=-1>Figure 9 : 
        Pinout of CDP6402</FONT> </CENTER></TD>
      <TD>
        <P>There are UARTs such as the CDP6402, AY-5-1015 / D36402R-9 and 
        compatibles. These differ from the 8250 and compatibles, by the fact 
        that they have separate Receive and Transmit data buses and can be 
        configured by connecting certain pins to various logic levels. These are 
        ideal for applications where you don't have a Microprocessor available. 
        Such an example is if you want to connect a ADC0804 (Analog to Digital 
        Converter) to the UART, or want to connect a LCD Display to the Serial 
        Line. These common devices use a 8 bit parallel data bus. </P>
        <P>The CDP6402's <I>Control Register</I> is made up of Parity Inhibit 
        (PI), Stop Bit Select (SBS), Character Length Select (CLS1 and 2) and 
        Even Parity Enable (EPE). These inputs can be latched using the Control 
        Register Load (CRL) or if you tie this pin high, changes made to these 
        pins will immediately take effect. </P></TD></TR></TBODY></TABLE>
  <P>
  <CENTER>
  <TABLE width="90%" border=1>
    <TBODY>
    <TR>
      <TD><B>Pin Number</B></TD>
      <TD><B>Abbr.</B></TD>
      <TD><B>Full Name</B></TD>
      <TD><B>Notes</B></TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 1</CENTER></TD>
      <TD>
        <CENTER>VDD</CENTER></TD>
      <TD>+ 5v Supply Rail</TD>
      <TD>&nbsp;</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 2</CENTER></TD>
      <TD>
        <CENTER>NC</CENTER></TD>
      <TD>Not Connected</TD>
      <TD>&nbsp;</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 3</CENTER></TD>
      <TD>
        <CENTER>GND</CENTER></TD>
      <TD>Ground</TD>
      <TD>&nbsp;</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 4</CENTER></TD>
      <TD>
        <CENTER>RRD</CENTER></TD>
      <TD>Receiver Register Disable</TD>
      <TD>When driven high, outputs RBR8:RBR1 are High Impedance.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 5:12</CENTER></TD>
      <TD>
        <CENTER>RBR8:<BR>RBR1</CENTER></TD>
      <TD>Receiver Buffer Register</TD>
      <TD>Receiver's Data Bus </TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 13</CENTER></TD>
      <TD>
        <CENTER>PE</CENTER></TD>
      <TD>Parity Error</TD>
      <TD>When High, A Parity Error Has Occurred.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 14</CENTER></TD>
      <TD>
        <CENTER>FE</CENTER></TD>
      <TD>Framing Error</TD>
      <TD>When High, A Framing Error Has Occurred. i.e. The Stop Bit was not a 
        Logic 1.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 15</CENTER></TD>
      <TD>
        <CENTER>OE</CENTER></TD>
      <TD>Overrun Error</TD>
      <TD>When High, Data has been received but the nData Received Reset had 
        not yet been activated.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 16</CENTER></TD>
      <TD>
        <CENTER>SFD</CENTER></TD>
      <TD>Status Flag Disable</TD>
      <TD>When High, Status Flag Outputs (PE, FE, OE, DR and TBRE) are High 
        Impedance </TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 17</CENTER></TD>
      <TD>
        <CENTER>RRC</CENTER></TD>
      <TD>Receiver Register Clock</TD>
      <TD>x16 Clock input for the Receiver Register.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 18</CENTER></TD>
      <TD>
        <CENTER>nDRR</CENTER></TD>
      <TD>Data Received Reset</TD>
      <TD>Active Low. When low, sets Data received Output Low (i.e. Clears 
      DR)</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 19</CENTER></TD>
      <TD>
        <CENTER>DR</CENTER></TD>
      <TD>Data Received</TD>
      <TD>When High, Data has been received and placed on outputs RBR8:RBR1. 
      </TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 20</CENTER></TD>
      <TD>
        <CENTER>RRI</CENTER></TD>
      <TD>Receiver Register In</TD>
      <TD>RXD - Serial Input. Connect to Serial Port, Via RS-232 
    receiver.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 21</CENTER></TD>
      <TD>
        <CENTER>MR</CENTER></TD>
      <TD>Master Reset</TD>
      <TD>Resets the UART. <I>UART should be reset after applying 
    power.</I></TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 22</CENTER></TD>
      <TD>
        <CENTER>TBRE</CENTER></TD>
      <TD>Transmitter Buffer Register Empty</TD>
      <TD>When High, indicates that Transmitter Buffer Register is Empty, thus 
        all bits including the stop bit have been sent.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 23</CENTER></TD>
      <TD>
        <CENTER>nTBRL</CENTER></TD>
      <TD>Transmitter Buffer Load / Strobe</TD>
      <TD>Active Low. When low, data present on TBR8:TBR1 is placed in 
        Transmitter Buffer Register. A Low to High Transition on this pin, then 
        sends the data.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 24</CENTER></TD>
      <TD>
        <CENTER>TRE</CENTER></TD>
      <TD>Transmitter Register Empty</TD>
      <TD>When High, Transmitter Register is Empty, thus can accept another 
        byte of data to be sent.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 25</CENTER></TD>
      <TD>
        <CENTER>TRO</CENTER></TD>
      <TD>Transmitter Register Out (TXD)</TD>
      <TD>TXD - Serial Output. Connect to Serial Port, Via RS-232 
      Transmitter.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 26:33</CENTER></TD>
      <TD>
        <CENTER>TBR8:<BR>TBR1</CENTER></TD>
      <TD>Transmitter Buffer Register</TD>
      <TD>Data Bus, for Transmitter. Place Data here which you want to 
    send.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 34</CENTER></TD>
      <TD>
        <CENTER>CRL</CENTER></TD>
      <TD>Control Register Load</TD>
      <TD>When High, Control Register (PI, SBS, CLS2, CLS1, EPE) is Loaded. 
        <I>Can be tied high, so changes on these pins occur 
      instantaneously.</I></TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 35</CENTER></TD>
      <TD>
        <CENTER>PI</CENTER></TD>
      <TD>Parity Inhibit</TD>
      <TD>When High, No Parity is Used for Both Transmit and Receive. When 
        Low, Parity is Used.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 36</CENTER></TD>
      <TD>
        <CENTER>SBS</CENTER></TD>
      <TD>Stop Bit Select</TD>
      <TD>A High selects 2 stop bits. (1.5 for 5 Character Word Lengths) A Low 
        selects one stop bit.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 37:38</CENTER></TD>
      <TD>
        <CENTER>CLS2:<BR>CLS1</CENTER></TD>
      <TD>Character Length Select</TD>
      <TD>Selects Word Length. 00 = 5 Bits, 01 = 6 Bits, 10 = 7 Bits and 11 = 
        8 Bits.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 39</CENTER></TD>
      <TD>
        <CENTER>EPE</CENTER></TD>
      <TD>Even Parity Enable</TD>
      <TD>When High, Even Parity is Used, When Low, Odd Parity is Used.</TD></TR>
    <TR>
      <TD>
        <CENTER>Pin 40</CENTER></TD>
      <TD>
        <CENTER>TRC</CENTER></TD>
      <TD>Transmitter Register Clock</TD>
      <TD>16x Clock input for Transmitter.</TD></TR></TBODY></TABLE><FONT 
  size=-1>Table 18 : Pin Description for CDP6402, AY-5-1015 / D36402R-9 and 
  compatible UART's</FONT> </CENTER>
  <P>
  <P>However one disadvantage of these chips over the 8250's is that these 
  UART's have no inbuilt Programmable Baud Rate Generator, and no facility to 
  connect a crystal directly to it. While there are Baud Rate Generator Chips 
  such as the AY-5-8116, a more cheaper <I>(and common)</I> alternative is the 
  74HC4060 14-bit Binary Counter and Oscillator. </P>
  <P>The 74HC4060, being a 14 bit binary counter/divider only has outputs for 
  some of it's stages. Only Q4 to Q14 is available for use as they have external 
  connections. This means higher Baud Rates are not obtainable from common 
  crystals, such as the 1.8432 Mhz and 2.4576 Mhz. The UART requires a clock 
  rate 16 times higher than the Baud Rate you will be using. eg A baud rate of 
  9600 BPS requires a input clock frequency of 153.6 Khz. </P>
  <CENTER>
  <TABLE>
    <TBODY>
    <TR>
      <TD width="50%">
        <CENTER><IMG alt="Baud Rate Generator using a 74HC4060" 
        src="serial1_files/74hc4060.gif" border=0> <BR><FONT size=-1>Figure 10 : 
        Baud Rate Generator using a 74HC4060</FONT> </CENTER></TD>
      <TD width="50%">
        <CENTER>
        <TABLE width="100%" border=1>
          <TBODY>
          <TR>
            <TD><B>
              <CENTER>Output</CENTER></B></TD>
            <TD><B>
              <CENTER>1.8432Mhz</CENTER></B></TD>
            <TD><B>
              <CENTER>2.4546Mhz</CENTER></B></TD></TR>
          <TR>
            <TD>
              <CENTER>Out 2</CENTER></TD>
            <TD>
              <CENTER>115.2 KBPS</CENTER></TD>
            <TD>
              <CENTER>153.6 KBPS</CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>Q4</CENTER></TD>
            <TD>
              <CENTER>7200 BPS</CENTER></TD>
            <TD>
              <CENTER>9600 BPS</CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>Q5</CENTER></TD>
            <TD>
              <CENTER>3600 BPS</CENTER></TD>
            <TD>
              <CENTER>4800 BPS</CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>Q6</CENTER></TD>
            <TD>
              <CENTER>1800 BPS</CENTER></TD>
            <TD>
              <CENTER>2400 BPS</CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>Q7</CENTER></TD>
            <TD>
              <CENTER>900 BPS</CENTER></TD>
            <TD>
              <CENTER>1200 BPS</CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>Q8</CENTER></TD>
            <TD>
              <CENTER>450 BPS</CENTER></TD>
            <TD>
              <CENTER>600 BPS</CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>Q9</CENTER></TD>
            <TD>
              <CENTER>225 BPS</CENTER></TD>
            <TD>
              <CENTER>300 BPS</CENTER></TD></TR></TBODY></TABLE><FONT size=-1>
        <CENTER>Table 19 : Possible Baud Rates using a 74HC4060 
        </CENTER></FONT></CENTER></TD></TR></TBODY></TABLE></CENTER>
  <P>The 1.8432 Mhz crystal gives some unfamiliar Baud Rates. While many of 
  these won't be accepted by terminal programs or some hardware, they are still 
  acceptable if you write your own serial programs. For example the PC's baud 
  rate divisor for 7200 BPS is 16, 3600 BPS is 32, 1800 BPS is 64 etc. If you 
  require higher speeds, then it is possible to connect the UART to the OUT2 
  pin. This connection utilizes the oscillator, but has no frequency division 
  applied. Using OUT2 with a 1.8432 Mhz crystal connected gives a baud rate of 
  115,200 BPS. The CMOS CDP6402 UART can handle up to 200 KBPS at 5 volts, 
  however your MAX-232 may be limited to 120 KBPS, but is still within range. 
  </P><BR><A name=46><FONT size=+1>Microcontrollers</FONT><BR>
  <HR>
  </A>
  <P>It is also possible to use microcontrollers to transmit and receive Serial 
  data. As we have already covered, some of these MCU's (Micro Controller Units) 
  have built in UART's among other things. Take the application we have used 
  above. We want to monitor analog voltages using a ADC and then send them 
  serially to the PC. If the Microcontroller also has a ADC built in along with 
  the UART or SCI, then we could simply program the device and connect a RS-232 
  Line Driver. This would minimize your chip count and make your PCB much 
  smaller. </P>
  <P>Take the second example, displaying the serial data to a common 16 
  character x 2 line LCD display. A common problem with the LCD modules, is they 
  don't accept cartridge returns, line-feeds, form-feeds etc. By using a 
  microcontroller, not only can you emulate the UART, but you can also program 
  it to clear the screen, should a form-feed be sent or advance to the next line 
  should a Line-feed be sent. </P>
  <P>The LCD example also required some additional logic (An Inverter) to reset 
  the data receive line on the UART, and provide a -ve edge on the enable of the 
  LCD to display the data present on the pins. This can all be done using the 
  Microcontroller and thus reducing the chip count and the cost of the project. 
  </P>
  <P>Talking of chip count, most Microcontrollers have internal oscillators thus 
  you don't require the 74HC4060 14 Bit Binary Counter and Oscillator. Many 
  Microcontrollers such as the 68HC05J1A and PIC16C84 have a smaller pin count, 
  than the 40 Pin UART. This not only makes the project smaller in size, it 
  reduces complexity of the PCB. </P>
  <P>But there are also many disadvantages of the Microcontroller. The major 
  one, is that you have to program it. For the hobbyist, you may not have a 
  development system for a Microcontroller or a method of programming it. Then 
  you have to learn the micro's code and work out how to tackle the problem. At 
  least with the UART, all you did was plug it in, wire it up and it worked. You 
  can't get much simpler that that. </P>
  <P>So far we have only discussed Full Duplex Transmission, that is that we can 
  transmit and receive at the same time. If our Microcontroller doesn't have a 
  SCI then we can <I>Emulate</I> a RS-232 port using a Parallel line under 
  software control. However Emulation has it's dis-advantages. It only supports 
  slow transmission speeds, commonly 2400, 9600 or maybe even 19,200 BPS if you 
  are lucky. The other disadvantage is that it's really only effective in half 
  duplex mode. That is, it can only communicate in one direction at any one 
  given time. However in many applications this is not a problem. </P>
  <P>As there are many different types of Micro-Controllers all with their 
  different instruction sets, it is very hard to give examples here which will 
  suit everyone. Just be aware that you can use them for serial communications 
  and hopefully at a later date, I can give a limited number of examples with 
  one micro. </P></UL><BR><BR>
<CENTER>
<TABLE width="90%" border=0>
  <TBODY>
  <TR>
    <TD width="20%" bgColor=black height=25><FONT face=ARIAL color=white 
      size=2><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/serial/serial.htm#TOC">Table of 
      Contents</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=black height=25><FONT face=ARIAL color=white 
      size=2><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/serial/serial.htm#part1">Pt 1 
      Hardware</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=black height=25><FONT face=ARIAL color=white 
      size=2><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/serial/serial.htm#part2">Pt 2 
      Registers</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=black height=25><FONT face=ARIAL color=white 
      size=2><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/serial/serial1.htm#part3">Pt 3 
      Programming</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=black height=25><FONT face=ARIAL color=white 
      size=2><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/serial/serial1.htm#part4">Pt 4 External 
      Hardware</A></CENTER></B></FONT></TD></TR></TBODY></TABLE><BR>
<TABLE width="90%" border=0>
  <TBODY>
  <TR>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#PARALLEL">Parallel 
      Ports</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#SERIAL">Serial / RS-232 
      Ports</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#INTERRUPTS">Interrupts</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#ATKEYBOARDS">AT Keyboard 
      Ports</A></CENTER></B></FONT></TD>
    <TD width="20%" bgColor=blue height=25><FONT face=ARIAL color=white><B>
      <CENTER><A id=TITLEBLOCK 
      href="http://www.beyondlogic.org/index.html#USB">USB</A></CENTER></B></FONT></TD></TR></TBODY></TABLE>
<HR>
<FONT size=2>Copyright 1999-2000 <A 
href="mailto:cpeacock@senet.com.au(Craig%20Peacock)">Craig Peacock </A>- 
Saturday 11th November 2000. 
<HR>
</CENTER></FONT></BODY>
<!-- Mirrored from bos.asmhackers.net/docs/serial/docs/serial1.htm by HTTrack Website Copier/3.x [XR&CO'2013], Tue, 07 Oct 2014 11:24:20 GMT -->
</HTML>
